<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

namespace Common\TagLib;

defined('THINK_PATH') or exit();

/**
 * Description of xshtml
 *
 * @author SoChishun
 * @version 1.0.0
 * @since 1.0.0 2017-3-15
 */
class Xshtml extends \Think\Template\TagLib {

    protected $tags = array(
        // 标签定义： attr 属性列表 close 是否闭合（0:开放标签;1:闭合标签,默认1,起始和结束标签必须成对出现） alias 标签别名 level 嵌套层次
        'radio' => array('attr' => 'attrs', 'close' => 0),
        'checkbox' => array('attr' => 'attrs', 'close' => 0),
        'file' => array('attr' => 'attrs', 'close' => 0),
        'test' => array('attr' => 'attrs', 'close' => 0),
    );

    // 2017-3-15
    // example: {xshtml:radio name="status" data='array("1"=>"启用","0"=>"禁用")' value="data['status']|default='0'" /}
    public function _radio($tag, $content) {
        $data = empty($tag['data']) ? false : $tag['data'];
        if (!$data) {
            return '';
        }
        $name = empty($tag['name']) ? false : $tag['name'];
        $varname = $name ? str_replace('[]', '', $name) : ''; // 过滤name[]
        $parseStr = '<?php ';
        if (isset($tag['value']) && !empty($tag['value'])) {
            $valueExp = $this->parseVar($tag['value']);
            $parseStr .= '$radioVal_' . $varname . '=' . $valueExp . ';';
        }
        $parseStr .= '$radios_' . $varname . '=' . $data . ';';
        $parseStr .= 'foreach($radios_' . $varname . ' as $v=>$t):';
        $parseStr .= 'echo \'<label class="radio-inline"><input type="radio" name="' . $name . '" value="\',$v,\'"\',(($radioVal_' . $varname . '==$v)?\' checked="checked"\':\'\'),\'> \',$t,\'</label>\';';
        $parseStr .= 'endforeach;';
        $parseStr .= '?>';
        return $parseStr;
    }

    // 2017-3-15
    // example: {xshtml:checkbox name="is_lock" data='array("1"=>"是")' value="data['is_lock']" /}
    public function _checkbox($tag, $content) {
        $data = empty($tag['data']) ? false : $tag['data'];
        if (!$data) {
            return '';
        }
        $name = empty($tag['name']) ? false : $tag['name'];
        $varname = $name ? str_replace('[]', '', $name) : ''; // 过滤name[]
        $parseStr = '<?php ';
        if (isset($tag['value']) && !empty($tag['value'])) {
            $valueExp = $this->parseVar($tag['value']);
            $parseStr .= '$checkboxVal_' . $varname . '=' . $valueExp . ';';
            $parseStr .= '$checkboxVal_' . $varname . '=$checkboxVal_' . $varname . '?explode(\',\',$checkboxVal_' . $varname . '):$checkboxVal_' . $varname . ';';
        }
        $parseStr .= '$checkbox_' . $varname . '=' . $data . ';';
        $parseStr .= 'foreach($checkbox_' . $varname . ' as $v=>$t):';
        $parseStr .= 'echo \'<label class="checkbox-inline"><input type="checkbox" name="' . $name . '" value="\',$v,\'"\',((!empty($checkboxVal_' . $varname . ') && in_array($v,$checkboxVal_' . $varname . '))?\' checked="checked"\':\'\'),\'> \',$t,\'</label>\';';
        $parseStr .= 'endforeach;';
        $parseStr .= '?>';
        return $parseStr;
    }

    /**
     * 文件域
     * @param $attr
     * @param $content
     * @return string
     * @since 1.0 2014-12-3 by sutroon
     * @since 2.0 2017-3-21 SoChishun 重构为支持bootstrap样式
     * @example <xshtml:file name="thumbUrl" value="{$data.thumbUrl}" />
     */
    public function _file($tag, $content) {
        $name = empty($tag['name']) ? false : $tag['name'];
        if (isset($tag['value']) && !empty($tag['value'])) {
            $valueExp = $this->parseVar($tag['value']);
        } else {
            $valueExp = 'False';
        }
        $sattrs = $this->parseElementAttr($tag, array('value'));
        $parseStr .= '$fileVal_' . $name . '=' . $valueExp . ';';
        $parseStr .= 'if($fileVal_' . $name . '):';
        $parseStr .= '$fileExt_' . $name . ' = pathinfo($fileVal_' . $name . ', PATHINFO_EXTENSION);';
        $parseStr .= 'if ($fileExt_' . $name . ' && in_array($fileExt_' . $name . ', array(\'jpg\', \'jpeg\', \'png\', \'gif\', \'bmp\', \'tiff\'))) :';
        $parseStr .= '$str_' . $name . ' = \'<a href="\' . $fileVal_' . $name . ' . \'" target="_blank"><img class="img-rounded img-sm" src="\' . $fileVal_' . $name . ' . \'" alt="" /></a>\';';
        $parseStr .= 'else:';
        $parseStr .= '$str_' . $name . ' = \'<a href="\' . $fileVal_' . $name . ' . \'" target="_blank">\' . $fileVal_' . $name . ' . \'</a>\';';
        $parseStr .= 'endif;';
        $parseStr .= '$str_' . $name . ' .= \'<input type="file" ' . $sattrs . ' style="display: none;"/>\';';
        $parseStr = '<?php ' . $parseStr . ' ?><div class="btn-group btn-group-justified"><div class="btn-group"><div class="input-group"><?php echo $str_' . $name . ' ?><span class="input-group-btn"><a href="#" class="btn btn-default btn-sm" onclick="if($(this).text()==\'替换文件\'){$(this).text(\'取消替换\').parent().prev().show().prev().hide();}else{$(this).text(\'替换文件\').parent().prev().hide().prev().show();};return false;">替换文件</a></span></div></div></div>';
        $parseStr .= '<?php else: ?>';
        $parseStr .= '<input type="file" ' . $sattrs . ' />';
        $parseStr .= '<?php endif; ?>';
        return $parseStr;
    }

    public function _test($tag) {
        return 'taglib test success.';
    }

    /**
     * 模板变量解析,支持使用函数
     * 格式： {$varname|function1|function2=arg1,arg2}
     * @access public
     * @param string $varStr 变量数据
     * @return string
     */
    public function parseVar($varStr) {
        $varStr = trim($varStr);
        static $_taglibVarParseList = array();
        //如果已经解析过该变量字串，则直接返回变量值
        if (isset($_taglibVarParseList[$varStr]))
            return $_taglibVarParseList[$varStr];
        $parseStr = '';
        $varExists = true;
        if (!empty($varStr)) {
            $varArray = explode('|', $varStr);
            //取得变量名称
            $var = array_shift($varArray);
            if ('Think.' == substr($var, 0, 6)) {
                // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出
                $name = $this->parseThinkVar($var);
            } elseif (false !== strpos($var, '.')) {
                //支持 {$var.property}
                $vars = explode('.', $var);
                $var = array_shift($vars);
                switch (strtolower(C('TMPL_VAR_IDENTIFY'))) {
                    case 'array': // 识别为数组
                        $name = '$' . $var;
                        foreach ($vars as $key => $val)
                            $name .= '["' . $val . '"]';
                        break;
                    case 'obj':  // 识别为对象
                        $name = '$' . $var;
                        foreach ($vars as $key => $val)
                            $name .= '->' . $val;
                        break;
                    default:  // 自动判断数组或对象 只支持二维
                        $name = 'is_array($' . $var . ')?$' . $var . '["' . $vars[0] . '"]:$' . $var . '->' . $vars[0];
                }
            } elseif (false !== strpos($var, '[')) {
                //支持 {$var['key']} 方式输出数组
                $name = "$" . $var;
                preg_match('/(.+?)\[(.+?)\]/is', $var, $match);
                $var = $match[1];
            } elseif (false !== strpos($var, ':') && false === strpos($var, '(') && false === strpos($var, '::') && false === strpos($var, '?')) {
                //支持 {$var:property} 方式输出对象的属性
                $vars = explode(':', $var);
                $var = str_replace(':', '->', $var);
                $name = "$" . $var;
                $var = $vars[0];
            } else {
                $name = "$$var";
            }
            //对变量使用函数
            if (count($varArray) > 0)
                $name = $this->parseVarFunction($name, $varArray);
        }
        $_taglibVarParseList[$varStr] = $name;
        return $name;
    }

    /**
     * 对模板变量使用函数
     * 格式 {$varname|function1|function2=arg1,arg2}
     * @access public
     * @param string $name 变量名
     * @param array $varArray  函数列表
     * @return string
     */
    public function parseVarFunction($name, $varArray) {
        //对变量使用函数
        $length = count($varArray);
        //取得模板禁止使用函数列表
        $template_deny_funs = explode(',', C('TMPL_DENY_FUNC_LIST'));
        for ($i = 0; $i < $length; $i++) {
            $args = explode('=', $varArray[$i], 2);
            //模板函数过滤
            $fun = trim($args[0]);
            switch ($fun) {
                case 'default':  // 特殊模板函数
                    $name = '(isset(' . $name . ') && (' . $name . ' !== ""))?(' . $name . '):' . $args[1];
                    break;
                default:  // 通用模板函数
                    if (!in_array($fun, $template_deny_funs)) {
                        if (isset($args[1])) {
                            if (strstr($args[1], '###')) {
                                $args[1] = str_replace('###', $name, $args[1]);
                                $name = "$fun($args[1])";
                            } else {
                                $name = "$fun($name,$args[1])";
                            }
                        } else if (!empty($args[0])) {
                            $name = "$fun($name)";
                        }
                    }
            }
        }
        return $name;
    }

    /**
     * 将attr转为控件属性字符串
     * @param array $attr 属性数据
     * @param array $skip 过滤的数据
     * @return string
     * @since 1.0 2014-11-3 by sutroon
     */
    function parseElementAttr($attr, $skip) {
        $str = '';
        foreach ($attr as $k => $v) {
            if (is_array($skip) && in_array($k, $skip)) {
                continue;
            }
            $str .= ' ' . $k . '="' . $v . '"';
        }
        return $str;
    }

}
